/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package music.types;

import music.Chords.IntervalQuality;

/**
 *
 * @author TJ
 */
public enum Interval {
    PERFECT_UNISON("P1","d2", 0,1),
    MINOR_SECOND("m2","A1", 1,2),
    MAJOR_SECOND("M2","d3", 2,2),
    MINOR_THIRD("m3","A2", 3,3),
    MAJOR_THIRD("M3","d4", 4,3),
    PERFECT_FOURTH("P4","A3", 5,4),
    DIMINISHED_FIFTH("d5","A4", 6,5),
    PERFECT_FIFTH("P5","d6", 7,5),
    MINOR_SIXTH("m6","A5", 8,6),
    MAJOR_SIXTH("M6","d7", 9,6),
    MINOR_SEVENTH("m7","A6", 10,7),
    MAJOR_SEVENTH("M7","d8", 11,7),
    PERFECT_OCTAVE("P8","A7", 12,8),
    MINOR_NINTH("m9","A8", 13,9),
    MAJOR_NINTH("M9","d10", 14,9),
    MINOR_TENTH("m10","A9", 15,10),
    MAJOR_TENTH("M10","d11", 16,10),
    PERFECT_ELEVENTH("P11","A10", 17,11),
    DIMINISHED_TWELFTH("d12","A11", 18,12),
    PERFECT_TWELFTH("P12","d13", 19,12),
    MINOR_THIRTEENTH("m13","A12", 20,13),
    MAJOR_THIRTEENTH("M13","d14", 21,13),
    MINOR_FOUTEENTH("m14","A13", 22,14),
    MAJOR_FOUTEENTH("M14","d15", 23,14),
    PERFECT_TWO_OCTAVE("P15","A14", 24,15);
    private String name;
    private String altname;
    private int semitones;
    private int letterDiff;
    private Interval(String abbr,String altabbr,int tones, int gap) {
        name=abbr;
        letterDiff=gap;
        altname=altabbr;
        semitones=tones;
    }
    public static Interval findBySemitones(int s) {
        for(Interval e : Interval.values()){
            if(e.getSemitones()==s){
                return e;
            }
        }
        return null;
    }
    public static Interval findByName(String s) {
        for(Interval e : Interval.values()){
            if(e.getChromaticName().equals(s) || e.getDiatonicName().equals(s)){
                return e;
            }
        }
        return null;
    }
    public static int getScaleDegreeBetween(MidiNote n1,MidiNote n2) {
        int degree=0;
        if(n1.getMidi()>n2.getMidi()) {
            degree=n2.getName().charAt(0) -n1.getName().charAt(0);
            if(degree>0) {degree-=7;}
            int diff=n1.getMidi()-n2.getMidi();
            while(diff>=12) {
                degree-=7;
                diff-=12;
            }
        }else if(n1.getMidi()<n2.getMidi()) {
            degree=n2.getName().charAt(0) -n1.getName().charAt(0);
            if(degree<0) {degree+=7;}
            int diff=n2.getMidi()-n1.getMidi();
            while(diff>=12) {
                degree+=7;
                diff-=12;
            }
        }
        return degree;
    }
    public static MidiNote getIntervalAbove(MidiNote n, Interval i) {
        return getIntervalAbove(n,i,i.getScaleDegree());
    }
    public static MidiNote getIntervalAbove(MidiNote n, IntervalQuality q,int i) {
        if(i>=15) {
            int tmp=i;
            while(tmp>=15) {
                tmp-=7;
            }
            return getIntervalAbove(n,getInterval(q,tmp),i);
        }
        return getIntervalAbove(n,getInterval(q,i));
    }
    public static MidiNote getIntervalAbove(MidiNote n, Interval q,int i) {
        if(i<=0) {return n;}
        int oct=(i-1)/14;
        i=(i%8);
        if(i==0) {i=1;}
        char c=n.getName().charAt(0);
        c+=i-1;
        if(c-'G'>0){c=(char) ('A'+(c-'G')-1);}
        BaseNotes b=BaseNotes.valueOf(""+c);
        MidiNote ret=b.getNote();
        while(ret.getMidi()<n.getMidi()) {
            ret.shiftOctave(true);
        }
        String name=b.name();
        int val=n.getMidi()+q.getSemitones();
        int off=val-ret.getMidi();
        while(Math.abs(off)>=6) {
            ret.shiftOctave(off>0);
            off=val-ret.getMidi();
        }
        for(int i2=0;i2<Math.abs(off);) {
            if(off<0){
                name+="b";
                i2++;
            }else if(Math.abs(off)>=2) {name+="*";i2+=2;}
            else{name+="#";i2++;}
        }
        ret=new MidiNote(val,name);
        for(int i2=0; i2<oct;i2++){ret.shiftOctave(true);}
        return ret;
    }
    public static Interval getInterval(IntervalQuality q, int i) {
        String intName="";
        if(q==IntervalQuality.MAJOR && (i==1 ||i==4 || i==5 || i==8|| i==11 ||i==12|i==15)) {
            intName="P"+i;
        } else if(q==IntervalQuality.MINOR && (i==1 ||i==4 || i==5 || i==8 || i==11 ||i==12|i==15)){
            intName="d";
            if(i==1){intName+="8";}
            else {intName+=""+i;}
        }
        else{intName=q.getNotation()+""+i;}
        return Interval.findByName(intName);
    }
    public int getScaleDegree(){return letterDiff;}
    public int getSemitones() {return semitones;}
    public String getDiatonicName() {return name;}
    public String getChromaticName() {return altname;}
}
